package com.itdct.onflow.generator.template.web

import com.itdct.onflow.core.entity.BaseUserEntity
import com.itdct.onflow.generator.config.GeneratorConfig
import com.itdct.onflow.generator.model.ClassModel
import com.itdct.onflow.generator.model.CompareResultModel
import com.itdct.onflow.generator.model.FieldModel

/**
 * @author Zhouwx
 * @date 2025/8/26 14:19:40
 * @version 1.0
 * @description
 */
class VuePageTemplate(classModel: ClassModel, generatorConfig: GeneratorConfig) : BaseVueTemplate(classModel, generatorConfig) {
    init {
        filterFieldList.add("del")
        filterFieldList.add("version")
        filterFieldList.add("deleteUser")
        filterFieldList.add("deleteTime")
        filterFieldList.add("updateUser")
        filterFieldList.add("createUser")
    }

    override fun restPath(): String {
        return "${classModel.className}Page.vue"
    }

    override fun render(): String {
        return """
<script setup lang="tsx">
import { ContentWrap } from '@/components/ContentWrap'
import { Search } from '@/components/Search'
import { onMounted, ref } from 'vue'
import { Table } from '@/components/Table'
import { useRouter } from 'vue-router'
import { BaseButton } from '@/components/Button'
import { ${classModel.className}ListVo, ${classModel.className}SearchQo } from '@/api/${apiPath()}/types'
import { ${classModel.classNameLowCamel}DeleteApi, ${classModel.classNameLowCamel}PageApi } from '@/api/${apiPath()}'
import { AllSchemas, useBasePageView } from '@/base/views/BasePageView'
import { TableSortProps } from '@/components/Table/src/types'
import { ElText } from 'element-plus'
import { sysDictChooseListApi } from '@/api/system/dict/SysDict'
import { KeyLabelValueVo } from '@/base/api/KeyLabelValueVo'${accountSelectImport()}
${rangeStart("selectFunctionImport")}
${selectFunctionImport()}
${rangeEnd("selectFunctionImport")}

defineOptions({
  name: '${classModel.className}Page'
})
const { push } = useRouter()

const pageView = useBasePageView<${classModel.className}ListVo, ${classModel.className}SearchQo>('${classModel.className}')
const {
  pageInfo,
  delLoading,
  loading,
  dataList,
  baseGetList,
  searchParams,
  baseSortChange,
  datePickerShortcuts,
  registerRefreshEvent,
  editUrl,
  addUrl
} = pageView

const getList = async (params: any) => {
  await baseGetList(params, ${classModel.classNameLowCamel}PageApi)
}
pageView.doWatch(getList)
${rangeStart("dictFunctions")}
${renderDictFunctions()}
${rangeEnd("dictFunctions")}

${rangeStart("selectFunctions")}
${renderSelectFunctions()}
${rangeEnd("selectFunctions")}
${renderCreateUpdateUserSelectFunction()}

const delData = async (row: ${classModel.className}ListVo | null) => {
  await pageView.delData(row, ${classModel.classNameLowCamel}DeleteApi, () => {
    getList({ ...searchParams.value })
  })
}

const sortChange = async (sortProps: TableSortProps) => {
  await baseSortChange(sortProps, ${classModel.classNameLowCamel}PageApi)
}

const allSchemas = ref<AllSchemas>({
  searchSchema: [
    ${rangeStart("searchSchemas")}
${searchSchemas()}
    ${rangeEnd("searchSchemas")}
${createUpdateUserSchemas()}
  ],
  tableColumns: [
    {
      field: 'selection',
      type: 'selection'
    },
    {
      field: 'index',
      label: '序号',
      type: 'index',
      search: {
        hidden: true
      },
      form: {
        hidden: true
      },
      detail: {
        hidden: true
      }
    },
    ${rangeStart("tableColumns")}
${tableFields()}
    ${rangeEnd("tableColumns")}
${createUpdateUserFields()}
    {
      field: 'action',
      width: '260px',
      label: '操作',
      slots: {
        default: (data: any) => {
          return (
            <>
              <BaseButton type="primary" onClick={() => editData(data.row)} permission="'edit'">
                编辑
              </BaseButton>
              <BaseButton type="danger" onClick={() => delData(data.row)} permission="'delete'">
                删除
              </BaseButton>
            </>
          )
        }
      }
    }
  ]
})

const editData = (row: ${classModel.className}ListVo) => {
  push(`${"$"}{editUrl}?id=${"$"}{row.id}&type=edit`)
}

const addAction = () => {
  push(`${"$"}{addUrl}?type=add`)
}

onMounted(() => {
  getList({})
  registerRefreshEvent(${classModel.classNameLowCamel}PageApi)
})
</script>

<template>
  <ContentWrap>
    <Search
      :schema="allSchemas.searchSchema"
      @search="getList"
      @reset="getList"
      expandField="id"
      :searchLoading="loading"
      :resetLoading="loading"
    />

    <div class="mb-10px">
      <BaseButton type="primary" @click="addAction" permission="'add'">新增</BaseButton>
      <BaseButton :loading="delLoading" type="danger" @click="delData(null)" permission="'delete'">
        删除
      </BaseButton>
    </div>

    <Table
      v-model:pageSize="pageInfo.pageSize"
      v-model:currentPage="pageInfo.currentPage"
      :columns="allSchemas.tableColumns"
      :data="dataList"
      :loading="loading"
      :stripe="true"
      :pagination="{
        total: pageInfo.totalCount
      }"
      @register="pageView.tableRegister"
      @sort-change="sortChange"
    />
  </ContentWrap>
</template>

""".trimIndent()
    }

    private fun accountSelectImport(): String {
        val clazz = classModel.clazz ?: return ""
        if (BaseUserEntity::class.java.isAssignableFrom(clazz)) {
            val addContent = """
|
|import { selectSysAccountNameListApi } from '@/api/system/account/SysAccount'
            """.trimMargin()
            if (selectFunctionImport().contains(addContent)) {
                return ""
            } else {
                return addContent
            }
        } else {
            return ""
        }

    }

    private fun createUpdateUserFields(): String {
        val clazz = classModel.clazz ?: return ""
        if (BaseUserEntity::class.java.isAssignableFrom(clazz)) {
            return """
|    {
|      field: 'createUserName',
|      label: '创建人',
|      sortable: 'custom'
|    },
|    {
|      field: 'updateUserName',
|      label: '更新人',
|      sortable: 'custom'
|    },
            """.trimMargin()
        } else {
            return ""
        }
    }

    private fun createUpdateUserSchemas(): String {
        val clazz = classModel.clazz ?: return ""
        if (BaseUserEntity::class.java.isAssignableFrom(clazz)) {
            return """
|    {
|      field: 'createUser',
|      label: '创建人',
|      component: 'Select',
|      componentProps: {
|        placeholder: '请选择创建人',
|        clearable: true,
|        filterable: true,
|        options: sysAccountNameList
|      }
|    },
|    {
|      field: 'updateUser',
|      label: '更新人',
|      component: 'Select',
|      componentProps: {
|        placeholder: '请选择更新人',
|        clearable: true,
|        filterable: true,
|        options: sysAccountNameList
|      }
|    }
            """.trimMargin()
        } else {
            return ""
        }
    }

    private fun renderCreateUpdateUserSelectFunction(): String {

        val clazz = classModel.clazz ?: return ""
        if (BaseUserEntity::class.java.isAssignableFrom(clazz)) {
            val addContent = """
|
|const sysAccountNameList = ref<Array<KeyLabelValueVo>>([])
|const getSysAccountNameList = async () => {
|  const res = await selectSysAccountNameListApi({})
|  sysAccountNameList.value = res.data
|}
|getSysAccountNameList()
            """.trimMargin()
            if (renderSelectFunctions().contains(addContent)) {
                // INFO: Zhouwx: 2025/9/3 防止重复增加同一个方法
                return ""
            } else {
                return addContent
            }
        } else {
            return ""
        }
    }

    private fun tableFields(): String {
        val tempList = classModel.fieldList.filter {
            it.name != "id"
        }
        return fieldsGen("", tempList, { i, fieldModel ->
            tableFieldContent(fieldModel)
        }, ",\n") + ","
    }

    private fun tableFieldContent(fieldModel: FieldModel): String {
        return """
|    {
|      field: '${columnFieldName(fieldModel)}',
|      label: '${targetClassIdLabel(fieldModel)}'${sortable(fieldModel)}${columnFieldSlots(fieldModel)}
|    }
        """.trimMargin()
    }

    private fun sortable(fieldModel: FieldModel): String {
        if (fieldModel.sortable) {
            return """
|,
|      sortable: 'custom'
            """.trimMargin()
        } else {
            return ""
        }
    }

    private fun columnFieldSlots(fieldModel: FieldModel): String {
        if (fieldModel.kClass == Boolean::class) {
            // INFO: Zhouwx: 2025/8/26 布尔类型使用是和否来显示
            return ",\n" + """
|      slots: {
|        default: (data: any) => {
|          return (
|            <>
|              <ElText type={data.row.${fieldModel.name} ? 'success' : 'danger'}>
|                {data.row.${fieldModel.name} ? '是' : '否'}
|              </ElText>
|            </>
|          )
|        }
|      }
            """.trimMargin()
        } else if (fieldModel.targetClass != null) {
            return ",\n" + """
|      slots: {
|        default: (data: any) => {
|          return (
|            <>
|              <div
|                onClick={() => {
|                  push(`${getTargetEditPushUrl(fieldModel)}?id=${"$"}{data.row.${fieldModel.name}}&type=edit`)
|                }}
|              >
|                <ElText type="primary" style="cursor: pointer;">
|                  {data.row.${fieldModel.name}${fieldModel.idGenSuffix}}
|                </ElText>
|              </div>
|            </>
|          )
|        }
|      }
            """.trimMargin()
        } else if (fieldModel.dictCode.isNotBlank()) {
            return ",\n" + """
|      slots: {
|        default: (data: any) => {
|          return (
|            <>
|              <div>{data.row.${fieldModel.name + fieldModel.dictGenSuffix}}</div>
|            </>
|          )
|        }
|      }
            """.trimMargin()
        }
        return ""
    }

    private fun getTargetEditPushUrl(fieldModel: FieldModel): String {
        val targetClass = fieldModel.targetClass!!.java
        var packageName = targetClass.packageName
        if (packageName.endsWith(".entity")) {
            packageName = packageName.substring(0, packageName.length - 7)
        }
        val pushUrl = addEditPushUrl(packageName, fieldModel.targetClassName!!)
        return pushUrl + "Edit"
    }

    private fun columnFieldName(fieldModel: FieldModel): String {
        if (fieldModel.targetClass != null) {
            return fieldModel.name + fieldModel.idGenSuffix
        }

        return fieldModel.name
    }

    private fun searchSchemas(): String {
        var fieldsGen = fieldsGen("", classModel.fieldList, { i, fieldModel ->
            searchSchemaContent(fieldModel)
        }, ",\n")
        val clazz = classModel.clazz ?: return ""
        if (BaseUserEntity::class.java.isAssignableFrom(clazz)) {
            fieldsGen += ","
        }
        return fieldsGen
    }

    private fun searchSchemaContent(fieldModel: FieldModel) = """
|    {
|      field: '${fieldModel.name}',
|      label: '${targetClassIdLabel(fieldModel)}',
|      component: '${fieldModel.vueComponentType}',
|      componentProps: {
|        placeholder: '${placeholder(fieldModel)}'${extraOptions(fieldModel)}
|      }
|    }
    """.trimMargin()

    private fun extraOptions(fieldModel: FieldModel): String {
        val vueComponentType = fieldModel.vueComponentType
        if (vueComponentType == "Input" || vueComponentType == "InputNumber") {
            return ",\n" + """
|        clearable: true
            """.trimMargin()
        }
        var extra = ""

        if (vueComponentType == "Select") {
            var optionName = ""
            if (fieldModel.targetClass != null) {
                optionName = "${firstLetterLower(fieldModel.targetClassName)}${firstLetterUpper(fieldModel.targetFieldName)}List"
            }
            if (fieldModel.dictCode.isNotBlank()) {
                optionName = "${fieldModel.name}Options"
            }
            extra = "," + """
|
|        clearable: true,
|        filterable: true,
|        options: ${optionName}
            """.trimMargin()
        } else if (vueComponentType == "DatePicker") {
            extra = "," + """
|
|        clearable: true,
|        type: 'datetimerange',
|        valueFormat: 'YYYY-MM-DD HH:mm:ss',
|        shortcuts: datePickerShortcuts
            """.trimMargin()
        }
        return extra
    }

    private fun placeholder(fieldModel: FieldModel): String {
        if (fieldModel.vueComponentType == "Input") {
            return "请输入${fieldModel.comment}"
        } else {
            return "请选择${fieldModel.comment}"
        }
    }

    fun addEditPushUrl(packageName: String, className: String): String {
        var className = className
        if (className.endsWith("Entity")) {
            className = className.substring(0, className.length - 6)
        }
//        val packageName = classModel.packageName
        var url = packageName.replace(generatorConfig.groupId, "")
        if (url.startsWith(".")) {
            url = url.substring(1)
        }
        url = url.substring(0, 1).uppercase() + url.substring(1)
        val lastIndexOf = url.lastIndexOf(".")
        if (lastIndexOf > 0) {
            url = url.substring(0, lastIndexOf)
        }
        url = url.replace(".", "/")
        url = "/$url/$className/$className"
        return url
    }

    override fun onModify(compareResultModel: CompareResultModel, content: String): String {
        var content = content
        // INFO: Zhouwx: 2025/9/3 处理导入import行
        val addTargetFields = compareResultModel.addTargetFields
        var addIndex = content.indexOf(rangeEnd("selectFunctionImport"))
        content = insertFieldListContent(content, addTargetFields, addIndex, { index, fieldModel -> selectFunctionImportContent(fieldModel) })

        val delTargetFields = compareResultModel.delTargetFields
        content = deleteRangeFunctionCode(content, "selectFunctionImport", delTargetFields, { fieldModel -> selectFunctionImportContent(fieldModel) })

        // INFO: Zhouwx: 2025/9/3 处理字典相关内容
        val addDicts = compareResultModel.addDict
        addIndex = content.indexOf(rangeEnd("dictFunctions"))
        content = insertFieldListContent(content, addDicts, addIndex, { index, fieldModel -> selectDictContent(fieldModel) })

        val delDicts = compareResultModel.delDict
        content = deleteRangeFunctionCode(content, "dictFunctions", delDicts, { fieldModel -> selectDictContent(fieldModel) })

        val modifyDicts = compareResultModel.modifyDict
        content = modifyReplace(content, "dictFunctions", modifyDicts, { fieldModel -> selectDictContent(fieldModel) })

        // INFO: Zhouwx: 2025/9/3 处理下拉选相关内容
        addIndex = content.indexOf(rangeEnd("selectFunctions"))
        content = insertFieldListContent(content, addTargetFields, addIndex, { index, fieldModel -> selectFunctionContent(fieldModel) })

        content = deleteRangeFunctionCode(content, "selectFunctions", delTargetFields, { fieldModel -> selectFunctionContent(fieldModel) })

        // INFO: Zhouwx: 2025/9/3 处理选择框
        addIndex = content.indexOf(rangeEnd("searchSchemas"))
        content = insertFieldListContent(content, addTargetFields, addIndex, { index, fieldModel -> searchSchemaContent(fieldModel) })

        content = deleteRangeFunctionCode(content, "searchSchemas", delTargetFields, { fieldModel -> searchSchemaContent(fieldModel) })

        val modifyPairs = compareResultModel.modifyPairs
        content = modifyReplace(content, "searchSchemas", modifyPairs, { fieldModel -> searchSchemaContent(fieldModel) })

        // INFO: Zhouwx: 2025/9/3 处理表格列
        addIndex = content.indexOf(rangeEnd("tableColumns"))
        content = insertFieldListContent(content, addTargetFields, addIndex, { index, fieldModel -> tableFieldContent(fieldModel) })

        content = deleteRangeFunctionCode(content, "tableColumns", delTargetFields, { fieldModel -> tableFieldContent(fieldModel) })

        content = modifyReplace(content, "tableColumns", modifyPairs, { fieldModel -> tableFieldContent(fieldModel) })

        return content
    }

    override fun subModuleName(): String {
        return "views"
    }
}